package com.enlorenz.core.exception.common;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import com.enlorenz.common.util.DataDetUtils;
import com.enlorenz.common.util.ExceptionUtils;
import com.enlorenz.common.util.ExceptionUtils.IElzExceptionIterator;
import com.enlorenz.common.util.ReflectionUtils;
import com.enlorenz.common.util.ReflectionUtils.IFieldsIteratorCallback;
import com.enlorenz.core.exception.ElzBaseException;
import com.enlorenz.core.exception.ElzExpCode;


/**
 * Elz异常工具
 * @author lcb
 */
public class ElzExceptionUtil {
	
	/**
	 * 从class中获取异常map,主键为属性名
	 * @param claxx 类
	 * @return 异常Map
	 */
	public static List<ElzExpCodeDesp> getExpCodeListFromClass(Class<?> claxx){
		final List<ElzExpCodeDesp> expCodeList=new ArrayList<ElzExpCodeDesp>();
		ReflectionUtils.iterateFields(claxx, null, true, new IFieldsIteratorCallback(){
			@Override
			public void callback(Object obj, Class class1, Field field)
					throws Exception {
				if(field.getType().
						getName().equals(ElzExpCode.class.getName()) ){
					ElzExpCode value=(ElzExpCode)field.get(null);
					if(null!=value){
						expCodeList.add(new ElzExpCodeDesp(value, field.getName()));
					}
				}
			}
			
		});
		return expCodeList;
	}
	
	/**
	 * 异常码描述
	 * @author lcb
	 */
	public static class ElzExpCodeDesp extends ElzExpCode{
		//属性名
		private String fieldName;
		public ElzExpCodeDesp(ElzExpCode expCode,String fieldName) {
			super(expCode.getExpCode(), expCode.getExpCodeDesp());
			this.fieldName=fieldName;
		}
		public String getFieldName() {
			return fieldName;
		}
		public void setFieldName(String fieldName) {
			this.fieldName = fieldName;
		}
	}
	
	
	
	
    
    /**
     * 通过异常代码获取异常列表
     * @param throwable 异常
     * @param expCode 异常代码
     * @return 异常列表
     */
    public static List<ElzBaseException> getExpListByCode(Throwable throwable,final ElzExpCode expCode){
    	final List<ElzBaseException> list=new ArrayList<ElzBaseException>();
    	
    	ExceptionUtils.iterateThrowable(throwable, new IElzExceptionIterator() {
			
			@Override
			public boolean iterate(Throwable throwable) {
				if(throwable instanceof ElzBaseException){
		    		ElzBaseException blzExp=(ElzBaseException)throwable;
		    		if(blzExp.getExpCode().getExpCode().equals(expCode.getExpCode())){
		    			list.add(blzExp);
		    		}
		    	}
				return true;
			}
		});
    	
    	return list;
    }
    
    /**
     * 通过异常代码数组获取异常列表
     * @param throwable 异常
     * @param expCodeArr 异常代码数组
     * @return 异常列表
     */
    public static List<ElzBaseException> getExpListByCode(Throwable throwable,final ElzExpCode [] expCodeArr){
    	if(DataDetUtils.isArrEmpty(expCodeArr)){
    		return null;
    	}
    	
    	final List<ElzBaseException> list=new ArrayList<ElzBaseException>();
    	
    	ExceptionUtils.iterateThrowable(throwable, new IElzExceptionIterator() {
			@Override
			public boolean iterate(Throwable throwable) {
				if(throwable instanceof ElzBaseException){
		    		ElzBaseException blzExp=(ElzBaseException)throwable;
		    		for(ElzExpCode expCode:expCodeArr){
			    		if(blzExp.getExpCode().getExpCode().equals(expCode.getExpCode())){
			    			list.add(blzExp);
			    			break;
			    		}
		    		}
		    	}
				return true;
			}
		});
    	
    	return list;
    }
    
    
    
    /**
     * 获取异常信息列表
     * @param throwable 异常
     * @return 异常信息列表
     */
    public static List<String> getExpMsgList(Throwable throwable){
    	final List<String> list=new ArrayList<String>();
    	
    	ExceptionUtils.iterateThrowable(throwable, new IElzExceptionIterator() {
			
			@Override
			public boolean iterate(Throwable throwable) {
				list.add(throwable.getMessage());
				return true;
			}
		});
    	
    	return list;
    }
    
    
    /**
     * 通过异常代码获取单个异常
     * 如果有多个相同代码的异常，则只默认获取一个
     * @param throwable 异常
     * @param expCode 异常代码
     * @return 单个异常
     */
    public static ElzBaseException getExpByCode(Throwable throwable,final ElzExpCode expCode){
    	final ElzBaseException [] cause=new ElzBaseException[1];
    	ExceptionUtils.iterateThrowable(throwable, new IElzExceptionIterator() {
			
			@Override
			public boolean iterate(Throwable throwable) {
				if(throwable instanceof ElzBaseException){
		    		ElzBaseException blzExp=(ElzBaseException)throwable;
		    		if(blzExp.getExpCode().getExpCode().equals(expCode.getExpCode())){
		    			cause[0]=blzExp;
		    			return false;
		    		}
		    	}
				return true;
			}
		});
    	return cause[0];
    }
    
    /**
     * 获取栈底的ElzBaseException
     * @param throwable 异常
     * @return 单个异常
     */
    public static ElzBaseException getBottomElzExp(Throwable throwable){
    	ElzBaseException exp=(ElzBaseException)
    			getBottomExpByType(throwable, ElzBaseException.class);
    	return exp;
    }
    
    /**
     * 获取最底部的异常
     * @param throwable 异常
     * @param claxx 需要获取的异常类型
     * @return 结果异常
     */
    public static Throwable getBottomExpByType(Throwable throwable
    		,final Class<? extends Throwable> claxx){
    	final Throwable [] cause=new Throwable[1];
    	ExceptionUtils.iterateThrowable(throwable, new IElzExceptionIterator() {
			
			@Override
			public boolean iterate(Throwable throwable) {
				//符合传入class的所有子类
				if(claxx.isAssignableFrom(throwable.getClass())){
					cause[0]=throwable;
				}
				return true;
			}
		});
    	return (ElzBaseException)cause[0];
    }
    
    /**
     * 获取栈顶的Throwable
     * @param throwable 异常
     * @param claxx 异常类型
     * @return 单个异常
     */
    public static Throwable getTopElzExp(Throwable throwable,
    		final Class<? extends Throwable> claxx){
    	final Throwable [] cause=new Throwable[1];
    	ExceptionUtils.iterateThrowable(throwable, new IElzExceptionIterator() {
			@Override
			public boolean iterate(Throwable throwable) {
				if(claxx.isAssignableFrom(throwable.getClass())){
		    		cause[0]=throwable;
		    		return false;
		    	}
				return true;
			}
		});
    	return cause[0];
    }
    
    
    /**
     * 获取栈顶的ElzBaseException
     * @param throwable 异常
     * @return 单个异常
     */
    public static ElzBaseException getTopElzExp(Throwable throwable){
    	return (ElzBaseException)getTopElzExp(throwable, ElzBaseException.class);
    }
    
    
    
}
